/**
 * 常用数据格式验证器
 */
export class Validator {
    static url(url) {
        const regex = /^(https?|ftp):\/\/([a-zA-Z0-9.-]+(:[a-zA-Z0-9.&%$-]+)*@)*((25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9][0-9]?)(\.(25[0-5]|2[0-4][0-9]|1[0-9]{2}|[1-9]?[0-9])){3}|([a-zA-Z0-9-]+\.)*[a-zA-Z0-9-]+\.(com|edu|gov|int|mil|net|org|biz|arpa|info|name|pro|aero|coop|museum|[a-zA-Z]{2}))(:[0-9]+)*(\/($|[a-zA-Z0-9.,?"\\+&%$#=~_-]+))*$/;
        return Validator.valid(url, regex, 'URL格式不正确');
    }

    static lowerCase(str) {
        const regex = /^[a-z]+$/;
        return Validator.valid(str, regex, '只能输入小写字母');
    }

    static lowerCaseOrCharacter(str) {
        const regex = /^([a-z]|_|-)+$/;
        return Validator.valid(str, regex, '只能输入小写字母或者-或者_');
    }

    static upperCase(str) {
        const regex = /^[A-Z]+$/;
        return Validator.valid(str, regex, '只能输入大写字母');
    }

    static upperCaseOrCharacter(str) {
        const regex = /^([A-Z]|_|-)+$/;
        return Validator.valid(str, regex, '只能输入大写字母或者-或者_');
    }

    static alphabets(str) {
        const regex = /^[A-Za-z]+$/;
        return Validator.valid(str, regex, '只能输入字母');
    }

    static email(email) {
        const regex = /^(([^<>()\[\]\\.,;:\s@"]+(\.[^<>()\[\]\\.,;:\s@"]+)*)|(".+"))@((\[[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\])|(([a-zA-Z\-0-9]+\.)+[a-zA-Z]{2,}))$/;
        return Validator.valid(email, regex, '邮箱地址格式不正确');
    }

    static mobile(mobile) {
        const regex = /^1[34578][0-9]\d{8}$/;
        return Validator.valid(mobile, regex, '手机号格式不正确');
    }

    static phone(phone) {
        const regex = /^(0\d{2,3})?-?\d{7,8}$/;
        return Validator.valid(phone, regex, '电话号码格式不正确');
    }

    static postcode(postcode) {
        const regex = /^[0-9][0-9]{5}$/;
        return Validator.valid(postcode, regex, '邮编格式不正确');
    }

    static number(num) {
        const regex = /^\d+$/;
        return Validator.valid(num, regex, '只能输入纯数字');
    }

    static fax(fax) {
        const regex = /^(\d{3,4}-)?\d{7,8}$/;
        return Validator.valid(fax, regex, '传真格式不正确');
    }

    static int(num) {
        const regex = /^((0)|([1-9]\d*))$/;
        return Validator.valid(num, regex, '只能输入非负整数');
    }

    static intPlus(num) {
        const regex = /^[1-9]\d*$/;
        return Validator.valid(num, regex, '只能输入正整数');
    }

    static float1(num) {
        const regex = /^-?\d+(\.\d)?$/;
        return Validator.valid(num, regex, '只能输入数字，最多一位小数');
    }

    static float2(num) {
        const regex = /^-?\d+(\.\d{1,2})?$/;
        return Validator.valid(num, regex, '只能输入数字，最多两位小数');
    }

    static float3(num) {
        const regex = /^-?\d+(\.\d{1,3})?$/;
        return Validator.valid(num, regex, '只能输入数字，最多三位小数');
    }

    static floatPlus3(num) {
        const regex = /^\d+(\.\d{1,3})?$/;
        return Validator.valid(num, regex, '只能输入数字，最多三位小数');
    }

    static encode(code) {
        const regex = /^(_|-|[a-zA-Z0-9])+$/;
        return Validator.valid(code, regex, '编码只能使用字母、数字、下划线、中划线');
    }

    static encode2(code) {
        const regex = /^[a-zA-Z0-9]+$/;
        return Validator.valid(code, regex, '编码只能使用字母、数字');
    }

    static encode3(code) {
        const regex = /^(_|[a-zA-Z0-9])+$/;
        return Validator.valid(code, regex, '编码只能使用字母、数字、下划线');
    }

    static idCard(code) {
        const regex = /^[1-9]\d{5}(18|19|([23]\d))\d{2}((0[1-9])|(10|11|12))(([0-2][1-9])|10|20|30|31)\d{3}[0-9Xx]$/;
        return Validator.valid(code, regex, '请输入正确的身份证号码');
    }

    static uscc(code) {
        const regex = /^[0-9A-Z]{18}/;
        return Validator.valid(code, regex, '请输入正确的社会信用号');
    }

    static carNum(code) {
        const regex = /^(([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z](([0-9]{5}[DF])|([DF]([A-HJ-NP-Z0-9])[0-9]{4})))|([京津沪渝冀豫云辽黑湘皖鲁新苏浙赣鄂桂甘晋蒙陕吉闽贵粤青藏川宁琼使领][A-Z][A-HJ-NP-Z0-9]{4}[A-HJ-NP-Z0-9挂学警港澳使领]))$/i;
        return Validator.valid(code, regex, '请输入正确的车牌号');
    }

    static cnandEN(code) {
        const regex = /^[a-zA-Z\u4e00-\u9fa5]+$/;
        return Validator.valid(code, regex, '只能使用中文、英文');
    }

    static mobileOrPhone(val) {
        const result = /^1\d{10}$/.test(val) || /^(0\d{2,3})?-?\d{7,8}$/.test(val);
        return Validator.valid(result, null, '手机或电话号格式不正确');
    }

    static length(val) {
        return Validator.valid(val, null, '字符长度不正确');
    }

    static valid(val, regex, msg) {
        return {
            result: regex instanceof RegExp ? regex.test(val) : !!val,
            errMsg: msg
        };
    }
}

window.Validator = Validator;

/**
 * 是否是内网IPv4
 * @param required:Boolean 是否必填项，选填，默认"true"
 * @param type:String/Function 校验类型，选填，
 *             String时必须是上面rules中存在的函数名，
 *             Function时只接收一个参数(输入值)，返回格式： {result:Boolean, errMsg:String}
 * @param trigger:String 触发动作，选填，默认"blur"
 * @param nullMsg:String 未输入的提示语，选填，required=true时有效
 * @param min
 * @param max
 * @returns {Object}
 */
export function vxRule(required = true, type, trigger = 'blur', nullMsg = '该字段为必填项', min = null, max = null) {
    const rule = {
        required: !!required,
        trigger
    };
    let check = null;
    if (typeof type === 'function') {
        check = type;
    } else {
        check = type ? Validator[type] : null;
    }
    if (check) {//存在规则时添加规则
        rule.validator = (r, v, c) => {
            const {
                result,
                errMsg
            } = check(v);
            if (!!min && !!v && v.toString().length < min) {
                return c(new Error(nullMsg));
            }
            if (!!max && !!v && v.toString().length > max) {
                return c(new Error(nullMsg));
            }
            if (required) {
                //必填项: null,undefined,"","  " 都算无输入内容
                return (v == null || (v + '').trim() === '') ? c(new Error(nullMsg)) : result ? c() : c(new Error(errMsg));
            }
            //选填项: null,undefined,"" 都算无输入内容，"  "会被校验
            return (v == null || (v + '') === '' || result) ? c() : c(new Error(errMsg));
        };
    } else {
        rule.message = nullMsg;
    }
    return rule;
}
